#ifndef TABLE_INCLUDED

#include "numlist.h"
#include "file.h"
#include "mutex.h"



struct delayedBuff{
   int rec;
   int posTime;
   char *buff;
   int action;
};



typedef struct vlink{
	int recId;
	int size;
	char locked;
	char sync;
	short changed;
	void *table;
	vlink* right;
	vlink* left;
}VLINK;


typedef sortedList<delayedBuff> bufList;

/*
Packed structure containg the record info. Only for reference

struct FLAGDATA{
      int recordNo;
      char flag;
      char status;
      ULONG createdTime;
      ULONG modifiedTime;
      ULONG etag;
};
*/

#define FLAGP 4
#define STATUSP 5
#define CTIMEP 6
#define MTIMEP 10
#define ETAGP 14


typedef char DBINF[sizeof(int)+sizeof(char)*2+sizeof(ULONG)*3];
#define REPAIRDATA	1
#define REPAIRTABLE	2
#define SAVEINFO	4
#define NOMODIFY	8

class TableFile : public RealFile{
   enum {NEWPOS = -2, INVALID_VALUE = -1, FILLED = -2, RESERVED = 512, FREE=55,USED=77,INVALID=0,DELETED=57,UNUSED=58};
   enum DBACTION {PUT=0,DEL=1,ADD=2};
   struct DBINFO{
      int hole;
      int maxRec;
      int nHoles;
      int dataOffset;
      int recordSize;
      int dataSize;
      int metaSize;
      int flags;
      ULONG crc;
	  ULONG urecId;
	  ULONG urecIdCheck;
      };
   mutex *dbl;
   char bfile[256];
   static int infSize;
   int maxEntries();
   Buffer *header;
   int vSize;
   void flushBufs();
   int getRecordPosition(int);
   DBINFO inf;
   numList *indexes;
   numList *recPos;
   bufList *bufs;
   ULONG oldestWrite;
   ULONG writeHeader;
   int complete;
   int changed;
   void setRecordPos(int,int);
   void putIndex(int recordNo, int index);
   void writeInfo();
   int checkConsistency();
   int getRecord(int,char*);
   int bufferRec(char* recBuff,int recNo,DBACTION act);
   Buffer *recordBuff;
   void lock(){dbl->lock();}
   void release(){dbl->release();}

   public:
   char* getRecordBuff();
   int reopen();
   int needRepair(){return (inf.flags&REPAIRDATA);} 
   void forceRepair();
   void setNoModify();
   int nomodify(){return(inf.flags&NOMODIFY);}
   void RepairWasOK();
   int getRecordSize() { return inf.dataSize;}
   void flushDat();
   int flushDats(int must=0);
   TableFile(char* name,mutex *mtx,int RecSize=0, int firstRecPtr=512);
   ~TableFile();
   int operator[](int n) { if(indexes && indexes->getTotal()>n) return (*indexes)[n]; return 0;}
   int put(char* recbuff, int recno,ULONG createdtime=0);
   int bufferedPut(char* recbuff, int recno);
//   int getCacheLock(int recno);
   void trashBufs();
   int add(char* newrec, int recId=0);
   int bufferedAdd(char* newrec, int recId=0);
   int get(Buffer* recbuff, int recno);
   int getNext(int,int,int roll=0);
   int get(int recno,char *);
   ULONG getCreatedTime(int recno);
   ULONG getModifiedTime(int recno);
   void setRecordTime(int recno,ULONG ct,ULONG mt);
   void close();
   void setOffset(int n);
   void setRecordSize(int z);
   char*  getHeader(char* buff=0);
   void putHeader();
   void bufferedPutHeader() { writeHeader=1;}
   void putHeader(char* buff,int n=-1);
   int deleteRecord(int recno);
   int bufferedDeleteRecord(int recno);
   int getNewRecordNo();
   int isValidRecord(int);
   void deleteDB();
   Buffer *getValidList();
   int maxRecNumber() { return inf.maxRec;}
   int getTotal() { if (indexes) return indexes->getTotal(); return 0; }
   void justFlush(){if (changed){flush();changed=0;}}
   ULONG incUrecId();
   void setUrecId(ULONG n);
   void skip(int mx);
   void setLockable(mutex *m){dbl=m;}
   char* checkWriteBuffers(int);
  };

extern ULONG fcstab32[256];

TableFile* findOpenTable(char* thisfile);
extern int repair;

#define TABLE_INCLUDED
#endif














